package top.byfree.jbyan.saber.service

import cn.dev33.satoken.stp.StpUtil
import org.ktorm.dsl.eq
import org.ktorm.dsl.limit
import org.ktorm.dsl.map
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import top.byfree.jbyan.saber.bean.*
import top.byfree.jbyan.saber.bean.dto.FilterRoleDto
import top.byfree.jbyan.saber.bean.dto.PageDto
import top.byfree.jbyan.saber.bean.dto.RoleDto
import top.byfree.jbyan.saber.bean.pojo.Role
import top.byfree.jbyan.saber.bean.vo.RoleVo
import top.byfree.jbyan.saber.bean.vo.UserVo
import top.byfree.jbyan.saber.common.IdWorker
import top.byfree.jbyan.saber.dao.RoleDao
import top.byfree.jbyan.saber.dao.RolePermDao
import java.time.LocalDateTime

/**
 * 角色业务逻辑层
 *
 * @author jbyan
 * @since 26/3/2024
 */
@Service
open class RoleService(
    @Autowired open val roleDao: RoleDao,
    @Autowired open val idWorker: IdWorker,
    @Autowired open val rolePermDao: RolePermDao
) {

    /* 根据角色编号查询角色信息 */
    fun getOne(roleId: String): RoleVo? = roleDao.findOne { it.roleId eq roleId }?.toVo()

    /* 条件分页查询角色 */
    fun page(size: Int, current: Int, filterRoleDto: FilterRoleDto): PageDto<RoleVo> {
        // 通过 size 和 current 计算 offset 值
        val offset = size * current
        val query = roleDao.filter(filterRoleDto)
            .limit(offset, size)
        return PageDto(query.map(Roles::createEntity).map { it.toVo() }, query.totalRecordsInAllPages, current, size)
    }

    /* 新增一个角色 */
    fun add(roleDto: RoleDto) = roleDao.add(roleDto.toRole(idWorker.nextId(), Operate.OPERATE_ADD)) > 0

    /* 修改角色信息 */
    fun update(roleId: String, roleDto: RoleDto) = roleDao.update(roleDto.toRole(roleId, Operate.OPERATE_UPDATE)) > 0

    /* 逻辑删除角色信息 */
    fun delete(cRoleId: String) : Boolean {
        val userVo = (StpUtil.getSession().get("user") as? UserVo)!!
        val role = Role {
            roleId = cRoleId
            isDelete = IS_DELETE_YES
            modifyBy = userVo.userId
            gmtModify = LocalDateTime.now()
        }
        return roleDao.update(role) > 0
    }

    /* 修改角色权限列表 */
    @Transactional
    open fun editPerm(roleId: String, perms: MutableList<String>) {
        // 1. 删除角色全部权限关联
        rolePermDao.deleteIf { it.roleId eq roleId }
        // 2. 为角色新增权限关联信息
        rolePermDao.batchAdd {
            perms.forEach { permId ->
                item {
                    set(RolePerms.roleId, roleId)
                    set(RolePerms.permId, permId)
                }
            }
        }
    }
    /* 根据角色编号获取角色下所有权限信息 */
    fun getPermList(roleId: String) = roleDao.getPermList(roleId).map { it.toVo() }

}